package com.threadPool;

import java.lang.ref.WeakReference;
import java.util.concurrent.*;

public class ThreadPoolGCTest {
    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(2,4,1, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1024),new MyThreadFactory());
        executor.execute(()->System.out.println(Thread.currentThread().getName() + " run a task"));
        WeakReference<Executor> weakReference = new WeakReference<>(executor);
        executor = null;

        /**
         * 对象的回收机制：gcRoot是否可达
         * gcroot类型：
         * 虚拟机栈中的引用变量：这些变量通常存储在方法的局部变量表中，是当前正在执行的方法中使用的对象引用。例如，在一个方法中创建了一个对象并将其引用赋值给一个局部变量，这个局部变量就是根节点之一。
         * 方法区中的类静态属性引用：类的静态变量存储在方法区（或元空间）中，这些静态变量引用的对象也是根节点。例如，一个类有一个静态的成员变量，它引用了一个对象，那么这个对象在可达性分析中是可达的。
         * 方法区中的常量引用：字符串常量池中的字符串对象也是根节点。例如，通过String str = "hello";创建的字符串对象"hello"存储在字符串常量池中，它是一个根节点。
         * 本地方法栈中的JNI（Java Native Interface）引用：当Java代码调用本地方法（如C/C++代码）时，本地方法栈中可能会保存一些对Java对象的引用，这些引用也是根节点。
         *
         * 软引用（SoftReference）：软引用是对象的一种引用类型，它允许对象在内存不足时被回收。当垃圾回收器运行时，如果发现一个对象只被软引用引用，它会根据内存使用情况来决定是否回收这个对象。如果内存足够，软引用的对象不会被回收；如果内存不足，垃圾回收器会回收软引用的对象，以释放内存。
         * 弱引用（WeakReference）：弱引用的对象在垃圾回收器运行时会被回收，无论内存是否充足。弱引用通常用于实现一些缓存机制，例如，一个对象被弱引用引用，当垃圾回收器运行时，这个对象就会被回收，从而释放内存。
         * 虚引用（PhantomReference）：虚引用是对象的另一种引用类型，它不能单独使用，必须和引用队列（ReferenceQueue）一起使用。当垃圾回收器回收一个虚引用的对象时，它会将这个虚引用加入到引用队列中。通过监听引用队列，可以知道对象已经被回收，从而可以进行一些清理工作。
         */
        System.gc();

        // 当线程池没有执行任务时，executor强引用被断开，只有弱引用指向线程池，gc的时候就一定会被回收
        if(weakReference.get() == null){
            System.out.println("Thread pool is gc");
        }
        // 当线程池执行任务的时候，强引用被断开，只有弱引用
        // 但是创建的线程thread-》关联 worker（runnable），worker作为线程池的内部类，持有线程池的强引用
        // 所以线程池不会被回收
        else{
            System.out.println("Thread pool is not gc");
        }
    }

    static class MyThreadFactory implements ThreadFactory{
        @Override
        public Thread newThread(Runnable r) {
            Runnable newRunnable = ()->{
                System.out.println("task start");
                r.run();
                System.out.println("task end");
            };
            Thread thread = new Thread(newRunnable,"my Thread");
            System.out.println("Thread is created");
            return thread;
        }
    }

}
